package com.vecspace.security.proxy.dayu;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.vecspace.exception.HException;
import com.vecspace.security.model.SSOConsts;
import com.vecspace.security.proxy.service.LoginManager;
import com.vecspace.utils.TJSON;
import com.vecspace.web.servlet.model.StringWraper;


public class SSORestUtil {
	
	private static Logger logger = LoggerFactory.getLogger("httpInvoke");
	/**
	 * 调用http service的次数
	 */
	private static int ccount = 0;
	
	public static HttpEntity<MultiValueMap<String, Object>> createHttpRequestEntity() throws Exception {
		String loginToken = LoginManager.getLoginTokenFromSession();
		//有些请求是不需要登录就可以的		if(loginToken == null)throw new Exception("在请求SSO服务时，没有获取到登录token，无法发起请求。");		
		MultiValueMap<String, Object> postData = new LinkedMultiValueMap<>();
		HttpHeaders headers2 = new HttpHeaders();
		postData.add(SSOConsts.URL_PARAM_LOGIN_TOKEN, loginToken);
		headers2.add(SSOConsts.URL_PARAM_LOGIN_TOKEN, loginToken);
		headers2.addAll(headers2);
		headers2.setContentType(MediaType.APPLICATION_FORM_URLENCODED);//重要：一定不要改动，否则后台获取不要参数
		HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(postData, headers2);
		return requestEntity;
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T InvokeT(RestTemplate restTemplate, Class<T> returnType, String url, String methodName, String[] paramNames, Object... params) throws Exception{
		if(restTemplate == null) {
			throw new Exception("restTemplate对象为null，需要在Spring中定义一个RestTemplate对象");			
		}
		String fullUrl = url+"/"+methodName;
		Long tid = Thread.currentThread().getId();
		logger.info(++ccount+".thread:" + tid + " " + fullUrl);
		HttpEntity<MultiValueMap<String, Object>> requestEntity = createHttpRequestEntity();
		MultiValueMap<String, Object> postData = requestEntity.getBody();
		if(paramNames != null && paramNames.length > 0) {
			for(int i=0; i<paramNames.length; ++i) {
				String paranNane = paramNames[i];
				Object val = params[i];
				postData.add(paranNane, val);
			}
		}
		// 重要：headers的contentType一定要设置为APPLICATION_FORM_URLENCODED否则后台获取不要参数
        ResponseEntity<String> repEntity = restTemplate.exchange(fullUrl, HttpMethod.POST, requestEntity, String.class);
        String jsonText = repEntity.getBody();
		Object obj;
		if(jsonText != null && jsonText.length() > 0) {
			if(jsonText.contains("\"hasError\"") && jsonText.contains("\"errorMessage\"")){
				HashMap<?, ?> ex = TJSON.convertToObject(HashMap.class, jsonText);
				logger.error(jsonText);
				throw new HException((String)ex.get("errorMessage"), (String)ex.get("errorDetail"));
			}else {
				if(returnType.equals(void.class)) {
					obj = null;			
				}else {
					if(returnType.equals(String.class)){
						StringWraper wrap = TJSON.convertToObject(StringWraper.class, jsonText);
						obj = wrap.getText();
					}else{
						try{
							obj = TJSON.convertToObject(returnType, jsonText);
						}catch(Exception e){
							logger.error("error convert to " + returnType.toString() +":" + jsonText);
							throw new HException(e.getMessage());
						}
					}
				}
			}
		}else {
			obj = null;
		}
		return (T)obj;
	}
	
	/**
	 * 请求一次Web Service服务
	 * @param <T>返回值类型,返回的类型为ArrayList
	 * @param returnType 返回值的实际类型，即ArrayList中存储的数据的类型 如String.class Book.class
	 * @param wsUri
	 * @param methodName 请求的方法名
	 * @param params 参数列表
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> InvokeArrayList(RestTemplate restTemplate, Class<T> returnType, String url, String methodName, String[] paramNames, Object... params) throws Exception{
		if(restTemplate == null) {
			throw new Exception("restTemplate对象为null，需要在Spring中定义一个RestTemplate对象");			
		}
		String fullUrl = url+"/"+methodName;
		Long tid = Thread.currentThread().getId();
		logger.info(++ccount+".thread:"+tid+" "+fullUrl);
		if(returnType == null)throw new Exception("必须指定返回值的实际类型");

		HttpEntity<MultiValueMap<String, Object>> requestEntity = createHttpRequestEntity();
		MultiValueMap<String, Object> postData = requestEntity.getBody();
		if(paramNames != null && paramNames.length > 0) {
			for(int i=0; i<paramNames.length; ++i) {
				String paranNane = paramNames[i];
				Object val = params[i];
				postData.add(paranNane, val);
			}
		}
		String jsonText = restTemplate.postForObject(fullUrl, requestEntity, String.class);
		List<T> list = null;
		if(jsonText != null && jsonText.length() > 0) {			 
			if(jsonText.contains("\"hasError\"") && jsonText.contains("\"errorMessage\"")){
				HashMap<?, ?> ex = TJSON.convertToObject(HashMap.class, jsonText);
				if(ex.containsKey("hasError") && ex.containsKey("errorMessage")){
					throw new HException((String)ex.get("errorMessage"), (String)ex.get("errorDetail"));
				}
			}
			if(jsonText.startsWith("[")) {
				list = (List<T>) TJSON.convertToList(returnType, jsonText);
			}else {
				throw new Exception(jsonText);
			}
		}
		if(list == null) {
			list =  (List<T>) Collections.emptyList();
		}
		return list;
	}
}
